import java.util.Random;

import EnumerationPackage.ActionCode;
import EnumerationPackage.EventID;
import EventPackage.Event;
import EventPackage.EventManagerInterface;
import EventPackage.EventQueue;
import InstrumentationPackage.MessageWindow;


public class FireAlarmSensor {
	public static void main(String args[])
	{
		String EvtMgrIP;					// Event Manager IP address
		Event Evt = null;					// Event object
		EventQueue eq = null;				// Message Queue
		int EvtId = 0;						// User specified event ID
		EventManagerInterface em = null;	// Interface object to the event manager
		int	Delay = 2500;					// The loop delay (2.5 seconds)
		boolean Done = false;				// Loop termination flag

		boolean fireDetected = false;		//fire detection flag; a fire detected = true, no fire detect = false 
		boolean sprink = false;				//sprinkler status flag; on = true, off = false

		/////////////////////////////////////////////////////////////////////////////////
		// Get the IP address of the event manager
		/////////////////////////////////////////////////////////////////////////////////

		if ( args.length == 0 )
		{
			// event manager is on the local system

			System.out.println("\n\nAttempting to register on the local machine..." );

			try
			{
				// Here we create an event manager interface object. This assumes
				// that the event manager is on the local machine

				em = new EventManagerInterface();
			}

			catch (Exception e)
			{
				System.out.println("Error instantiating event manager interface: " + e);

			} // catch

		} else {

			// event manager is not on the local system

			EvtMgrIP = args[0];

			System.out.println("\n\nAttempting to register on the machine:: " + EvtMgrIP );

			try
			{
				// Here we create an event manager interface object. This assumes
				// that the event manager is NOT on the local machine

				em = new EventManagerInterface( EvtMgrIP );
			}

			catch (Exception e)
			{
				System.out.println("Error instantiating event manager interface: " + e);

			} // catch

		} // if

		// Here we check to see if registration worked. If em is null then the
		// event manager interface was not properly created.

		if (em != null)
		{
			System.out.println("Registered with the event manager.");
			// We create a message window. Note that we place this panel about 1/2 across 
			// and 2/3s down the screen

			float WinPosX = 0.5f; 	//This is the X position of the message window in terms 
			//of a percentage of the screen height
			float WinPosY = 0.60f;	//This is the Y position of the message window in terms 
			//of a percentage of the screen height 

			MessageWindow mw = new MessageWindow("Fire Alarm Sensor", WinPosX, WinPosY);

			mw.WriteMessage("Registered with the event manager." );

			try
			{
				mw.WriteMessage("   Participant id: " + em.GetMyId() );
				mw.WriteMessage("   Registration Time: " + em.GetRegistrationTime() );

			} // try

			catch (Exception e)
			{
				mw.WriteMessage("Error:: " + e);

			} // catch

			mw.WriteMessage("\nInitializing Fire Alarm Simulation::" );

			/********************************************************************
			 ** Here we start the main simulation loop
			 *********************************************************************/

			mw.WriteMessage("Beginning Simulation... ");


			while ( !Done )
			{

				// Get the message queue

				try
				{
					eq = em.GetEventQueue();

				} // try

				catch( Exception e )
				{
					mw.WriteMessage("Error getting event queue::" + e );

				} // catch

				int qlen = eq.GetSize();

				for ( int i = 0; i < qlen; i++ )
				{
					Evt = eq.GetEvent();

					if ( Evt.GetEventId() == EventID.SPRINK_CONFIRM.getEventIdNum() )
					{
						mw.WriteMessage("Received sprinkler confirmation event");
						if (Evt.GetMessage().equalsIgnoreCase(ActionCode.SPRINKLER_ON.getCode())) // security armed
						{
							sprink = true;
							
							//simulates the sprinklers dousing the fire
							//In reality, this should not occur immediately
							if (fireDetected){
								mw.WriteMessage("Fire doused");
								PostFireEvent(em, ActionCode.FIRE_DOUSED.getCode());
							}
							fireDetected = false;

						} // if

						else if (Evt.GetMessage().equalsIgnoreCase(ActionCode.SPRINKLER_OFF.getCode())) // security disarmed
						{
							sprink = false;
							mw.WriteMessage("Sprinklers deactivated");

						} // if

					} // if
					
					// If the event ID == 99 then this is a signal that the simulation
					// is to end. At this point, the loop termination flag is set to
					// true and this process unregisters from the event manager.

					if ( Evt.GetEventId() == EventID.DONE.getEventIdNum() )
					{
						Done = true;

						try
						{
							em.UnRegister();

						} // try

						catch (Exception e)
						{
							mw.WriteMessage("Error unregistering: " + e);

						} // catch

						mw.WriteMessage("\n\nSimulation Stopped. \n");

					} // if

				} // for

				// If the fire has not already been detected, and the sprinklers are not active,
				// determine whether a fire was detected
				// This reuses the randomZeroToTwo method used to determine security events
				// This has the system "roll" 0-2 twice to determine if a fire occurs
				// There is no real purpose, aside from not having to change the existing method 
				if(
						!fireDetected &&
						!sprink){
					switch (randomZeroToTwo()){
					case 0:
						switch (randomZeroToTwo()){
						case 0:
							mw.WriteMessage("Fire detected!\n");
							fireDetected = true;
							PostFireEvent(em, ActionCode.FIRE_DETECTED.getCode());
							break;
						}
						break;
					default:
						//no fire detected, do nothing
						break;
					}
				}

				try
				{
					Thread.sleep( Delay );

				} // try

				catch( Exception e )
				{
					mw.WriteMessage("Sleep error:: " + e );

				} // catch

			} // while

		} else {

			System.out.println("Unable to register with the event manager.\n\n" );

		} // if

	} // main

	/***************************************************************************
	 * CONCRETE METHOD:: randomZeroToTwo
	 * Purpose: This method provides a random zero to two to determine whether
	 * a fire is detected. 
	 *
	 * Arguments: None.
	 *
	 * Returns: integer
	 *
	 * Exceptions: None
	 *
	 ***************************************************************************/

	static private int randomZeroToTwo()
	{
		Random r = new Random();

		return(r.nextInt(3));

	} // CoinToss

	/***************************************************************************
	 * CONCRETE METHOD:: PostSecEvent
	 * Purpose: This method posts the specified security value to the
	 * specified event manager. This method assumes an event ID specified in the enumeration.
	 *
	 * Arguments: EventManagerInterface ei - this is the eventmanger interface
	 *			 where the event will be posted.
	 *
	 *			 String secEvtActionCode - the string representation of the 
	 *			 security event action code
	 *
	 * Returns: none
	 *
	 * Exceptions: None
	 *
	 ***************************************************************************/

	static private void PostFireEvent(EventManagerInterface ei, String message)
	{
		// Here we create the event.

		Event evt = new Event( EventID.FIRE.getEventIdNum(), message);

		// Here we send the event to the event manager.

		try
		{
			ei.SendEvent( evt );
			//mw.WriteMessage( "Sent Fire Alarm Event" );

		} // try

		catch (Exception e)
		{
			System.out.println( "Error Posting Fire Alarm Event:: " + e );

		} // catch

	} // PostFireEvent
}
